package com.xinke.module.system.service.user;

import cn.hutool.core.util.StrUtil;
import com.google.common.annotations.VisibleForTesting;
import com.mzt.logapi.starter.annotation.LogRecord;
import com.xinke.component.common.enums.CommonStatusEnum;
import com.xinke.component.common.util.collection.CollectionUtils;
import com.xinke.component.common.util.sno.IdGen;
import com.xinke.component.datapermission.core.util.DataPermissionUtils;
import com.xinke.module.system.mapper.user.AdminUserMapper;
import com.xinke.module.system.mapper.user.UserRoleMapper;
import com.xinke.module.system.model.entity.user.DeptDO;
import com.xinke.module.system.model.entity.user.UserRoleDO;
import com.xinke.module.system.service.permission.PermissionService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import com.xinke.module.system.model.vo.user.*;
import com.xinke.module.system.model.entity.user.AdminUserDO;
import com.xinke.component.common.pojo.PageResult;
import com.xinke.component.common.pojo.PageParam;
import com.xinke.component.common.util.object.BeanUtils;


import static com.xinke.component.common.exception.util.ServiceExceptionUtil.exception;
import static com.xinke.component.common.util.collection.CollectionUtils.convertSet;
import static com.xinke.component.common.util.collection.CollectionUtils.singleton;
import static com.xinke.module.system.enums.ErrorCodeConstants.*;
import static com.xinke.module.system.enums.LogRecordConstants.*;

/**
 * 用户信息 Service 实现类
 *
 * @author yzx
 */
@Service
@Validated
public class AdminUserServiceImpl implements AdminUserService {
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private AdminUserMapper userMapper;

    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private DeptService deptService;
    @Override
    public Long createAdminUser(AdminUserSaveReqVO createReqVO) {
        // 插入
        AdminUserDO adminUser = BeanUtils.toBean(createReqVO, AdminUserDO.class);
        userMapper.insert(adminUser);
        // 返回
        return adminUser.getUserId();
    }

    @Override
    public void updateAdminUser(AdminUserSaveReqVO updateReqVO) {
        // 校验存在
        validateAdminUserExists(updateReqVO.getUserId());
        // 更新
        AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class);
        userMapper.updateById(updateObj);
    }

    @Override
    public void deleteAdminUser(Long userId) {
        // 校验存在
        validateAdminUserExists(userId);
        // 删除
        userMapper.deleteById(userId);
    }

    private void validateAdminUserExists(Long userId) {
        if (userMapper.selectById(userId) == null) {
            throw exception(null);
        }
    }

    @Override
    public AdminUserDO getAdminUser(Long userId) {
        return userMapper.selectById(userId);
    }

    @Override
    public PageResult<AdminUserDO> getAdminUserPage(AdminUserPageReqVO reqVO) {
        // 如果有角色编号，查询角色对应的用户编号
        Set<Long> userIds = reqVO.getRoleId() != null ?convertSet(userRoleMapper.selectListByRoleIds(singleton(reqVO.getRoleId())), UserRoleDO::getUserId): null;

        // 分页查询
        return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds);
    }
    /**
     * 获得部门条件：查询指定部门的子部门编号们，包括自身
     *
     * @param deptId 部门编号
     * @return 部门编号集合
     */
    private Set<Long> getDeptCondition(Long deptId) {
        if (deptId == null) {
            return Collections.emptySet();
        }
        Set<Long> deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getDeptId);
        deptIds.add(deptId); // 包括自身
        return deptIds;
    }
    @Override
    public AdminUserDO getUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    @Override
    public void updateUserLogin(Long userId, String loginIp) {
        userMapper.updateById(new AdminUserDO().setUserId(userId).setLoginIp(loginIp).setLoginDate(LocalDateTime.now()));
    }

    @Override
    public Long selectCount() {
        return userMapper.selectCount();
    }


    @Override
    @VisibleForTesting
    public AdminUserDO validateUserExists(Long id) {
        if (id == null) {
            return null;
        }
        AdminUserDO user = userMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return user;
    }
    @Override
    @VisibleForTesting
    public void validateUsernameUnique(Long userId, String userName) {
        if (StrUtil.isBlank(userName)) {
            return;
        }
        AdminUserDO user = userMapper.selectByUsername(userName);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (userId == null) {
            throw exception(USER_USERNAME_EXISTS);
        }
        if (!user.getUserId().equals(userId)) {
            throw exception(USER_USERNAME_EXISTS);
        }
    }

    @Override
    @VisibleForTesting
    public void validateEmailUnique(Long id, String email) {
        if (StrUtil.isBlank(email)) {
            return;
        }
        AdminUserDO user = userMapper.selectByEmail(email);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_EMAIL_EXISTS);
        }
        if (!user.getUserId().equals(id)) {
            throw exception(USER_EMAIL_EXISTS);
        }
    }

    @Override
    public String encodePassword(String userPassword) {
        return passwordEncoder.encode(userPassword);
    }

    @Override
    public AdminUserDO insertUser(AdminUserSaveReqVO createReqVO) {
        AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
        user.setUserStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setUserPassword(passwordEncoder.encode(createReqVO.getUserPassword())); // 加密密码
        user.setUserId(IdGen.nextId());// 主键
        userMapper.insert(user);
        return user;
    }

    @Override
    @VisibleForTesting
    public void validateMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        AdminUserDO user = userMapper.selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_EXISTS);
        }
        if (!user.getUserId().equals(id)) {
            throw exception(USER_MOBILE_EXISTS);
        }
    }


}